﻿using System.Text;
using TrackSystem.IO.Data;
using TrackSystem.IO.Models;

namespace TrackSystem.IO.Protocol
{
    /// <summary>
    /// 声学所DVL通信协议
    /// 寄存器  只读
    /// 0 - 时间（年）
    /// 1 - 时间（月）
    /// 2 - 时间（日）
    /// 3 - 时间（时）
    /// 4 - 时间（分）
    /// 5 - 时间（秒）
    /// 6 - 盐度千分比（ppt）
    /// 7 - 温度（摄氏°）
    /// 8 - 换能器入水深度（m）
    /// 9 - 声速（m/s）
    /// 10 - 纵摇角度（pitch）
    /// 11 - 横摇角度（roll）
    /// 12 - 艏向角度（heading）
    /// 13 - DVL对底前向速度(mm/s)
    /// 14 - DVL对底右向速度(mm/s)
    /// 15 - DVL对底垂向速度(mm/s)
    /// 16 - DVL冗余速度--Z向速度的差值(mm/s)
    /// 17 - DVL对底数据质量
    /// 18 - DVL东向运动距离（m）
    /// 19 - DVL北向运动距离（m）
    /// 20 - DVL垂向运动距离（m）
    /// 21 - DVL对底距离（m）
    /// 22 - DVL距上次出现有效数据的时间（s）
    /// 
    /// </summary>
    public class DVLProtocol : ProtocolBase
    {
        private bool bSendR;
        private int startTicks;
        private bool IsSeaCal;      // 海上校准
        private bool IsFixPos;

        /// <summary>
        /// 初始状态  0 - 未通信  1-第一次成功通信 
        /// </summary>
        private int initState;
        private int INSState;

        private bool bFirst;
        private int bFirstCount;
        private int counter;


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="name"></param>
        public DVLProtocol(string name)
            : base()
        {
            Name = name;
            bSendR = false;
            NeedInit = false;
            // 首次进入
            bFirst = true;
            bFirstCount = 0;
        }

        /// <summary>
        /// 生成读取寄存器的通讯帧
        /// </summary>
        /// <param name="NeedRecvLen"></param>
        /// <returns></returns>
        public override byte[] GenerateReadFrame(out int NeedRecvLen)
        {
            // 首次上电进入，延时10次（10秒）再读取数据
            if (bFirst || bFirstCount < 10) {
                bFirst = false;
                bFirstCount++;
                NeedRecvLen = 0;
                return null;
            }

            // 上次的发送没有收到正确回复，bSend没有被置位
            startTicks = Environment.TickCount;

            // 上次的发送没有收到正确回复，bSend没有被置位
            if (bSendR)
            {
                Fail_R++;
                // 失败超过60次，成功次数清零
                if (Fail_R >= 60)
                {
                    Succ_R = 0;
                }
            }
            bSendR = true;

            // 接收数据长度定义
            NeedRecvLen = 50;
            Tx_r = null;
            return null;
        }

        /// <summary>
        /// 处理读取的数据
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessReadFrame(byte[] buffer)
        {
            Lapse = Environment.TickCount - startTicks;
            var DataFactory = RegFactory.Instance;

            Succ_R++;
            // 失败次数清零
            if (Succ_R > 30 && Fail_R>0) {
                Fail_R = 0;
            }
            bSendR = false;
            try
            {
                string fmCodes = Encoding.ASCII.GetString(buffer);
                Rx_r = buffer;  // 用于显示的接收帧内容
                string[] fmLines = fmCodes.Split('\n');
                foreach (var line in fmLines)
                {
                    string[] fmItems = line.Split(',');
                    int fmLen = fmItems.Length;

                    if (fmLen == 0)   // 数据长度为0
                    {
                        continue;
                    }

                    // ---  :SA,±PP.PP,±RR.RR,±HH.HH
                    if (fmLen == 4 && fmItems[0] == ":SA" && fmItems[3].Length>0)
                    {
                        double d1 = double.Parse(fmItems[1]);
                        double d2 = double.Parse(fmItems[2]);
                        double d3 = double.Parse(fmItems[3]);
                        DataFactory.SetVal(RegNameList[10], d1);
                        DataFactory.SetVal(RegNameList[11], d2);
                        DataFactory.SetVal(RegNameList[12], d3);
                        continue;
                    }

                    // ---  :TS,YYMMDDHHmmsshh,SS.S,+TT.T,DDDD.D,CCCC.C,BBBB
                    if (fmLen == 7 && fmItems[0] == ":TS")
                    {

                        double d1_Y = double.Parse(fmItems[1].Substring(0, 2)); // 年
                        double d1_M = double.Parse(fmItems[1].Substring(2, 2)); // 月
                        double d1_D = double.Parse(fmItems[1].Substring(4, 2)); // 日
                        double d1_H = double.Parse(fmItems[1].Substring(6, 2)); // 时
                        double d1_m = double.Parse(fmItems[1].Substring(8, 2)); // 分
                        double d1_s = (double.Parse(fmItems[1].Substring(10, 4)))/100; // 秒 ss.ss

                        DataFactory.SetVal(RegNameList[0], d1_Y);
                        DataFactory.SetVal(RegNameList[1], d1_M);
                        DataFactory.SetVal(RegNameList[2], d1_D);
                        DataFactory.SetVal(RegNameList[3], d1_H);
                        DataFactory.SetVal(RegNameList[4], d1_m);
                        DataFactory.SetVal(RegNameList[5], d1_s);

                        double d2 = double.Parse(fmItems[2]);
                        double d3 = double.Parse(fmItems[3]);
                        double d4 = double.Parse(fmItems[4]);
                        double d5 = double.Parse(fmItems[5]);

                        DataFactory.SetVal(RegNameList[6], d2);
                        DataFactory.SetVal(RegNameList[7], d3);
                        DataFactory.SetVal(RegNameList[8], d4);
                        DataFactory.SetVal(RegNameList[9], d5);
                        continue;
                    }

                    // --- :BI,±XXXXX,±YYYYY,±ZZZZZ,EEEE,S
                    if (fmLen == 6 && fmItems[0] == ":BI" && fmItems[5].Length > 0)
                    {
                        double d1 = double.Parse(fmItems[1]);
                        double d2 = double.Parse(fmItems[2]);
                        double d3 = double.Parse(fmItems[3]);
                        double d4 = double.Parse(fmItems[4]);
                        int d5 = 0;
                        if (fmItems[5][0] == 'A')
                            d5 = 1;
                        else if (fmItems[5][0] == 'V')
                            d5 = 0;

                        DataFactory.SetVal(RegNameList[13], d2);
                        DataFactory.SetVal(RegNameList[14], d1);
                        DataFactory.SetVal(RegNameList[15], d3);
                        DataFactory.SetVal(RegNameList[16], d4);
                        DataFactory.SetVal(RegNameList[17], d5);
                        continue;
                    }

                    // --- :BD,±EEEEEEEE.EE,±NNNNNNNN.NN,±UUUUUUUU.UU,DDDD.D,TTT.TT
                    if (fmLen == 6 && fmItems[0] == ":BD" && fmItems[5].Length > 0)
                    {
                        double d1 = double.Parse(fmItems[1]);
                        double d2 = double.Parse(fmItems[2]);
                        double d3 = double.Parse(fmItems[3]);
                        double d4 = double.Parse(fmItems[4]);
                        double d5 = double.Parse(fmItems[5]);
                        DataFactory.SetVal(RegNameList[18], d2);
                        DataFactory.SetVal(RegNameList[19], d1);
                        DataFactory.SetVal(RegNameList[20], d3);
                        DataFactory.SetVal(RegNameList[21], d4);
                        DataFactory.SetVal(RegNameList[22], d5);
                        continue;
                    }
                }
            }
            catch (Exception)
            {
                return false;
            }                
            return true;
        }

        /// <summary>
        /// 产生发送帧
        /// </summary>
        /// <param name="NeedRecvLen"></param>
        /// <returns></returns>
        public override byte[] GenerateWriteFrame(out int NeedRecvLen)
        {
            startTicks = Environment.TickCount;
            NeedRecvLen = 50;
            return null;
        }

        /// <summary>
        /// 处理写入帧的返回数据
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public override bool ProcessWriteFrame(byte[] buffer)
        {
            WriteFlag = false;
            return ProcessReadFrame(buffer);
        }

        /// <summary>
        /// 改变变量的值
        /// </summary>
        /// <param name="Index"></param>
        /// <param name="Value"></param>
        public override void PushRegValue(int Index, double Value)
        {
        }
    }
}
